聊聊Android编译流程 | 您所在的位置:网站首页 › desugar android › 聊聊Android编译流程 |
各位大佬,能不能随便给我的项目或者之前的文章点个star,苦兮兮。github.com/ 掘金文章 面试官:哟,大叔,又来了啊。 我:emmmmm,我今天就是来屠龙了。 面试官:勇气可嘉,那么我们聊聊Android编译流程吧。 我:吃我一招天打雷劈屠真龙。 是时候表演真正的技术了正常情况下,编译流程都是从下图说起的。 看起来我们貌似已经回答出了这个问题的答案,但是今天是来屠龙的,所以我们不能就这么简单的放过这个题目。 从gradle Task看编译流程先贴一段gradle打印task耗时的代码 项目根目录build.gradle打开 加入下面代码 import java.util.concurrent.TimeUnit // Log timings per task. class TimingsListener implements TaskExecutionListener, BuildListener { private long startTime private timings = [] @Override void beforeExecute(Task task) { startTime = System.nanoTime() } @Override void afterExecute(Task task, TaskState taskState) { def ms = TimeUnit.MILLISECONDS.convert(System.nanoTime() - startTime, TimeUnit.NANOSECONDS); timings.add([ms, task.path]) task.project.logger.warn "${task.path} took ${ms}ms" } @Override void buildFinished(BuildResult result) { println "Task timings:" for (timing in timings) { if (timing[0] >= 50) { printf "%7sms %s\n", timing } } } @Override void buildStarted(Gradle gradle) {} @Override void projectsEvaluated(Gradle gradle) {} @Override void projectsLoaded(Gradle gradle) {} @Override void settingsEvaluated(Settings settings) {} } gradle.addListener new TimingsListener() 复制代码当项目运行完之后会输出类似如下的日志,表示一个run执行之后gradle所执行的task的时间以及任务名。 1543ms :compiler:kaptGenerateStubsKotlin 144ms :RouterLib:packageDebugResources 1166ms :compiler:kaptKotlin 816ms :compiler:compileKotlin 401ms :compiler:compileJava 65ms :compiler:jar 122ms :app:mergeDebugResources 56ms :EmptyLoader:compileJava 170ms :app:processDebugManifest 171ms :RouterLib:parseDebugLocalResources 60ms :app:checkDebugDuplicateClasses 2416ms :RouterLib:compileDebugKotlin 122ms :RouterLib:compileDebugJavaWithJavac 124ms :secondmoudle:mergeDebugNativeLibs 1185ms :app:processDebugResources 70ms :secondmoudle:kaptGenerateStubsDebugKotlin 202ms :RouterLib:mergeDebugNativeLibs 350ms :secondmoudle:kaptDebugKotlin 158ms :secondmoudle:compileDebugJavaWithJavac 1108ms :app:kaptGenerateStubsDebugKotlin 91ms :secondmoudle:bundleLibRuntimeToJarDebug 129ms :app:mergeDebugNativeLibs 430ms :app:kaptDebugKotlin 1008ms :app:compileDebugKotlin 120ms :app:compileDebugJavaWithJavac 265ms :app:mergeDebugJavaResource 181ms :app:transformClassesAndResourcesWithAuto_registerForDebug 7262ms :app:dexBuilderDebug 1308ms :app:mergeProjectDexDebug 344ms :app:packageDebug 复制代码从上述Task列表中可以看出,其实最上面这张图所说的编译流程其实并不完整。 kapt和apt我上篇文章说了,javaCompiler执行之前会先执行apt,生成java代码,其任务名就是kaptGenerateStubsDebugKotlin。 聊聊AbstractProcessor和Java编译流程 compiler 混入了奇怪的东西kotlin已经被引入了很多版本了,但是kotlin的compiler其实和java compiler是不一样的。 如果按照标准答案去回答这个问题吧,总感觉还是有所欠缺的,所以我们需要补充的一个点就是compileDebugKotlin。 当然少不了transform当我们使用字节码插桩之后其实就增加了个transform的流程,也就是这个transformClassesAndResourcesWithAuto_registerForDebug。 那么是不是还有什么可以补充的呢?AGP在不同版本的差异还是比较大的。特别是在3.2版本之上的版本被引入了D8编译器之后。 低版本先使用DX编译器将class转化为dex。 而高版本采用d8编译器将class转化为dex。 Android Studio 为使用部分 Java 8 语言功能及利用这些功能的第三方库提供内置支持。默认工具链对 javac 编译器的输出执行字节码转换(称为 desugar),从而实现新语言功能。 语法糖香归香,但是最后.dex可是不认识你的。 那么D8的优势是什么呢???话不多,直接上图。 可以看到D8在编译速度以及编译出来的文件体积上有了明显的提升。 那么混淆呢??看看最一开始的图,有没有发现少了混淆的流程呢!!! 在AGP3.4版本上引入了R8,也就是混淆升级版本。而且在高版本上,整体流程也其实发生了微妙的变更,将原先的流程进行了合并。 R8开启前的编译流程说句题外话,但是R8更吃内存,机器辣鸡的老哥慎重点。 关于签名之前写的东西有点遗漏啊,谷歌官方有说明,下面是引用啊 注意:您必须在应用构建过程中的两个特定时间点之一使用 zipalign,具体在哪个时间点使用,取决于您所使用的应用签名工具: 如果您使用的是 apksigner,则只能在为 APK 文件签名之前执行 zipalign。如果您在使用 apksigner 为 APK 签名之后对 APK 做出了进一步更>改,签名便会失效。 如果您使用的是 jarsigner,则只能在为 APK 文件签名之后执行 zipalign。 链接地址 那么当使用V1签名时,编译流程顺序还是6-7 而当使用的是V2的签名时,则编译流程顺序是7-6 结束其实并没有什么想说的,只是想给各位老哥表演下倒立吹牛逼。觉得还ok 给我点个赞把。万一有哪个倒霉蛋下次再被问到这个题目,可以来这里上个香。 |
CopyRight 2018-2019 实验室设备网 版权所有 |